package org.vectrics.user;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.log4j.Logger;
import org.vectrics.common.db.Auditable;
import org.vectrics.common.db.OwnedObject;
import org.vectrics.common.db.RecordObject;
import org.vectrics.domain.Domain;
import org.vectrics.user.User;

import org.vectrics.hibernate.ThreadProperties;

import com.hexacta.hrs.securitygroups.SecurityGroup;

/**
 * @author mmoore
 */
public class User implements OwnedObject, RecordObject, Serializable, Auditable {
	
	public static final long serialVersionUID = 771234501623L;

    public static String EVENT_CREATED = "user.created";

    public static String MARITAL_STATUS_SINGLE = "single";
	public static String MARITAL_STATUS_MARRIED = "married";
	public static String MARITAL_STATUS_DIVORCED = "divorced";
	public static String MARITAL_STATUS_NOT_GIVEN = "not-given";
	public static int MINIMUM_PASSWORD_SIZE = 6;
	public static String OBJECT_TYPE = "user";
	
	private Vector historyList = new Vector();
    private Long id = null;
	private transient static Logger log = Logger.getLogger(User.class);
	private String userName;
	private String password;
	private boolean passwordEncrypted = false;
	private Domain domain = null;
	private boolean active = true;
	private Set userPrivileges = new HashSet();
	private Person person = null;
	private String passwordHintAnswer = null;
	private PasswordHintQuestion passwordHintQuestion = null;
	private Person createdBy = null;
	private Date createdDate = null;
	private Person lastModifiedBy = null;
	private Date lastModifiedDate = null;
	private Set<SecurityGroup> securityGroups = new HashSet<SecurityGroup>();
	
    /**
     * @return Returns the id.
     */
    public Long getId() {
        return id;
    }
    
    /**
     * @param id The id to set.
     */
    public void setId(Long id) {
        this.id = id;
    }	
    
    /**
	 * @return Returns the domain.
	 */
	public Domain getDomain() {
		return domain;
	}

	/**
	 * @param domain The domain to set.
	 */
	public void setDomain(Domain domain) {
		this.domain = domain;
	}

	public boolean equals(User otherUser) {
    	return(this.getId().equals(otherUser.getId()));
    }
    
    
    public Person getPerson() {
        return person;
    }
    
    public void setPerson(Person person) {
        this.person = person;
        
    }
    
	/**
	 * @return Returns the userPrivileges.
	 */
	public Set getUserPrivileges() {
		return userPrivileges;
	}
	/**
	 * @param userPrivileges The userPrivileges to set.
	 */
	public void setUserPrivileges(Set userPrivileges) {
		this.userPrivileges = userPrivileges;
	}
	
	/**
	 * 
	 * @return new empty User
	 */
	public static User createUser() {
		User user = new User();
		user.setDomain(ThreadProperties.getDomain());
		return user;
	}
	
	
	protected User() {
		super();
	}

	public int compareTo(Object other) {
		int result = this.getId().compareTo(((User)other).getId());	
		return(result);
	}

	public Collection getComponentList() {
		// TODO
		return(null);
	}  

	/**
	 * @hibernate.property
	 *  column="active"
	 *  not-null="true"
	 */
	public boolean getActive() {
		return(active);
	}
	public void setActive(boolean value) {
		this.active = value;
	}
/*    
    public void setContactInfo(ContactInfo contact) {
    	this.contactInfo = contact;
    }
    
	public ContactInfo getContactInfo() {
		return(contactInfo);		
	}
	
	public ContactInfo getCreateContactInfo() {
		if (contactInfo == null) {
			contactInfo = new ContactInfoImpl();
		}
		return(contactInfo);		
	}
*/

	public void setUserName(String name) {
		if (name != null)
			this.userName = name.toLowerCase();
		else 
			this.userName = name;
		
	}
	
	public String getUserName() {
		return(this.userName);
	}
    
	public void setPassword(String password) {
		this.password = password;
	}
	
	public String getPassword() {
		return(this.password);
	}
    
	public boolean getPasswordEncrypted() {
		return passwordEncrypted;
	}

	public void setPasswordEncrypted(boolean passwordEncrypted) {
		this.passwordEncrypted = passwordEncrypted;
	}

	public Collection findHistoryList() {
		return(historyList);
	}
	
	public void addHistory(String action, String userId, String description) {
		throw new NoSuchMethodError("'addHistory' has not been implemented");
	}

	public Collection findHistoryListFor() {
		return(findHistoryList());
	}
	
	public Collection findHistoryListBy() {
		return(null);
	}

/*	public void copy(User user) {
		this.active = user.getActive();
		this.lastModifiedDate = user.getLastModifiedDate();
		this.createdDate = user.getCreatedDate();
		this.createdBy = user.getCreatedBy();
		this.lastModifiedBy = user.getLastModifiedBy();
		this.password = user.getPassword();
		this.userName = user.getUserName();
		this.passwordHintAnswer = user.getPasswordHintAnswer();
		this.passwordHintQuestion = user.getP
	}	
*/

	/**
	 * @return Returns the passwordHintAnswer.
	 */
	public String getPasswordHintAnswer() {
		return passwordHintAnswer;
	}
	
	/**
	 * @param passwordHintAnswer The passwordHintAnswer to set.
	 */
	public void setPasswordHintAnswer(String passwordHintAnswer) {
		this.passwordHintAnswer = passwordHintAnswer;
	}
	
	/**
	 * @return Returns the passwordHintQuestion.
	 */
	public PasswordHintQuestion getPasswordHintQuestion() {
		return passwordHintQuestion;
	}
	
	/**
	 * @param passwordHintQuestion The passwordHintQuestion to set.
	 */
	public void setPasswordHintQuestion(PasswordHintQuestion passwordHintQuestion) {
		this.passwordHintQuestion = passwordHintQuestion;
	}

	/**
	 * @return Returns the createdBy.
	 */
	public Person getCreatedBy() {
		return createdBy;
	}

	/**
	 * @param createdBy The createdBy to set.
	 */
	public void setCreatedBy(Person createdBy) {
		this.createdBy = createdBy;
	}

	/**
	 * @return Returns the createdDate.
	 */
	public Date getCreatedDate() {
		return createdDate;
	}

	/**
	 * @param createdDate The createdDate to set.
	 */
	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}

	/**
	 * @return Returns the lastModifiedBy.
	 */
	public Person getLastModifiedBy() {
		return lastModifiedBy;
	}

	/**
	 * @param lastModifiedBy The lastModifiedBy to set.
	 */
	public void setLastModifiedBy(Person lastModifiedBy) {
		this.lastModifiedBy = lastModifiedBy;
	}

	/**
	 * @return Returns the lastModifiedDate.
	 */
	public Date getLastModifiedDate() {
		return lastModifiedDate;
	}

	/**
	 * @param lastModifiedDate The lastModifiedDate to set.
	 */
	public void setLastModifiedDate(Date lastModifiedDate) {
		this.lastModifiedDate = lastModifiedDate;
	}
	
	public boolean logEntityChanges() {
		return(true);
	}

	public String toString() {
		StringBuffer str = new StringBuffer();
		str.append("UserName=" + this.userName);
		str.append(" ");
		if (this.password != null) {
			str.append("Password=" + this.password.hashCode());
			str.append(" ");
		} else {
			str.append("Password=NULL");
			str.append(" ");
		}
		str.append(" PaswordEncrypted=" + this.passwordEncrypted );
		str.append("HintAns=" + this.passwordHintAnswer);
		str.append(" ");
		
		return(str.toString());
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;		
		if (obj == null)
			return false;
		if (!obj.getClass().isAssignableFrom(getClass())) 
			return false;
		User other = (User) obj;
		return new EqualsBuilder().append(this.userName, other.userName)
		                          .append(this.password, other.password)
		                          .isEquals();
	}
	
	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(this.getUserName())
		                            .append(this.password)
		                            .toHashCode();
	}

	public Set<SecurityGroup> getSecurityGroups() {
		return securityGroups;
	}

	public void setSecurityGroups(Set<SecurityGroup> securityGroups) {
		this.securityGroups = securityGroups;
	}

	
}
